<!DOCTYPE html>

<html lang="zh-CN">

<head>
    
    <title>使用RESTful风格 - 塔纳托斯</title>
    <meta charset="UTF-8">
    <meta name="keywords" content="">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=5">
    
    

    <link rel="shortcut icon" href="/favicon.ico" type="image/x-icon" />
    <meta name="description" content="REST，Representational State Transfer，表现层状态转化。 REST介绍REST是一种软件架构风格，是一种设计风格，不是一种必须的标准 其具有的特点：  以资源为基础  资源可以是对象数据，及一种资源可以是一个单体对象，一个集合，通常用JSON当作载体；同时资源也可以是二进制数据，及一种资源可以是图片、视频、音乐等等。概括总结的话，资源就是网络上的实体对象  统一接">
<meta property="og:type" content="article">
<meta property="og:title" content="使用RESTful风格">
<meta property="og:url" content="http://hai-chao.gitee.io/blog/2022/01/29/25.shi-yong-restful-feng-ge/index.html">
<meta property="og:site_name" content="塔纳托斯">
<meta property="og:description" content="REST，Representational State Transfer，表现层状态转化。 REST介绍REST是一种软件架构风格，是一种设计风格，不是一种必须的标准 其具有的特点：  以资源为基础  资源可以是对象数据，及一种资源可以是一个单体对象，一个集合，通常用JSON当作载体；同时资源也可以是二进制数据，及一种资源可以是图片、视频、音乐等等。概括总结的话，资源就是网络上的实体对象  统一接">
<meta property="og:locale" content="zh_CN">
<meta property="article:published_time" content="2022-01-29T08:00:00.000Z">
<meta property="article:modified_time" content="2022-01-30T03:25:19.389Z">
<meta property="article:author" content="塔纳托斯">
<meta property="article:tag" content="学习">
<meta name="twitter:card" content="summary">
    <link rel="stylesheet" href="/blog/lib/jquery.fancybox.min.css?v=1679297521091">
    
    <link rel="stylesheet" href="/blog/lib/mdui_043tiny/css/mdui.css?v=1679297521091">
    <link rel="stylesheet" href="/blog/lib/iconfont/iconfont.css?v=1679297521091">
    <link rel="stylesheet" href="/blog/css/style.css?v=1679297521091">
     
    
<meta name="generator" content="Hexo 5.3.0"><link rel="alternate" href="/blog/atom.xml" title="塔纳托斯" type="application/atom+xml">
<link rel="stylesheet" href="/blog/css/prism-tomorrow.css" type="text/css"></head>

<body class="mdui-drawer-body-left">
    
    <div id="nexmoe-background">
        <div class="nexmoe-bg" style="background-image: url(https://cdn.jsdelivr.net/gh/nexmoe/nexmoe.github.io@latest/images/cover/5c3aec85a4343.jpg)"></div>
        <div class="mdui-appbar mdui-shadow-0">
            <div class="mdui-toolbar">
                <a mdui-drawer="{target: '#drawer', swipe: true}" title="menu" class="mdui-btn mdui-btn-icon mdui-ripple"><i class="mdui-icon nexmoefont icon-menu"></i></a>
                <div class="mdui-toolbar-spacer"></div>
                <!--<a href="javascript:;" class="mdui-btn mdui-btn-icon"><i class="mdui-icon material-icons">search</i></a>-->
                <a href="/blog/" title="塔纳托斯" class="mdui-btn mdui-btn-icon"><img src="https://s6.jpg.cm/2022/01/17/LFpniO.md.jpg" alt="塔纳托斯"></a>
            </div>
        </div>
    </div>
    <div id="nexmoe-header">
        <div class="nexmoe-drawer mdui-drawer" id="drawer">
    <div class="nexmoe-avatar mdui-ripple">
        <a href="/blog/" title="塔纳托斯">
            <img src="https://s6.jpg.cm/2022/01/17/LFpniO.md.jpg" alt="塔纳托斯" alt="塔纳托斯">
        </a>
    </div>
    <div class="nexmoe-count">
        <div><span>文章</span>29</div>
        <div><span>标签</span>6</div>
        <div><span>分类</span>0</div>
    </div>
    <div class="nexmoe-list mdui-list" mdui-collapse="{accordion: true}">
        
        <a class="nexmoe-list-item mdui-list-item mdui-ripple false" href="/blog/" title="文章归档">
            <i class="mdui-list-item-icon nexmoefont icon-container"></i>
            <div class="mdui-list-item-content">
                文章归档
            </div>
        </a>
        
    </div>
    <aside id="nexmoe-sidebar">
    
    
  <div class="nexmoe-widget-wrap">
    <div id="randomtagcloud" class="nexmoe-widget tagcloud nexmoe-rainbow">
      <a href="/blog/tags/java/" style="font-size: 10px;">java</a> <a href="/blog/tags/%E5%88%86%E4%BA%AB/" style="font-size: 20px;">分享</a> <a href="/blog/tags/%E5%90%83%E7%93%9C/" style="font-size: 10px;">吃瓜</a> <a href="/blog/tags/%E5%AD%A6%E4%B9%A0/" style="font-size: 16.67px;">学习</a> <a href="/blog/tags/%E6%80%BB%E7%BB%93/" style="font-size: 13.33px;">总结</a> <a href="/blog/tags/%E6%B8%B8%E5%90%8E%E6%84%9F/" style="font-size: 10px;">游后感</a>
    </div>
    
  </div>

    
</aside>
    <div class="nexmoe-copyright">
        &copy; 2023 塔纳托斯
        Powered by <a href="http://hexo.io/" target="_blank">Hexo</a>
        & <a href="https://github.com/theme-nexmoe/hexo-theme-nexmoe" target="_blank">Nexmoe</a>
        
    </div>
</div><!-- .nexmoe-drawer -->
    </div>
    <div id="nexmoe-content">
        <div class="nexmoe-primary">
            <div class="nexmoe-post">

  <article>
      
          <div class="nexmoe-post-cover"> 
              
              <h1>使用RESTful风格</h1>
          </div>
      
      
      <div class="nexmoe-post-meta nexmoe-rainbow" style="margin:10px 0!important;">
    <a><i class="nexmoefont icon-calendar-fill"></i>2022年01月29日</a>
</div>

      

      <p>REST，Representational State Transfer，<strong>表现层状态转化</strong>。</p>
<h2 id="REST介绍"><a href="#REST介绍" class="headerlink" title="REST介绍"></a>REST介绍</h2><p>REST是一种软件架构风格，是一种设计风格，不是一种<strong>必须的标准</strong></p>
<p>其具有的特点：</p>
<ul>
<li>以资源为基础</li>
</ul>
<p>资源可以是<strong>对象数据</strong>，及一种资源可以是一个单体对象，一个集合，通常用JSON当作载体；同时资源也可以是<strong>二进制数据</strong>，及一种资源可以是图片、视频、音乐等等。概括总结的话，资源就是网络上的实体对象</p>
<ul>
<li>统一接口</li>
</ul>
<p>RESTful风格的接口，如<code>/classes</code>只能定位资源，而无法知道对资源进行了什么操作。想知道发生了什么操作需要具体分析<strong>HTTP请求方法</strong></p>
<ul>
<li>URL指向资源</li>
</ul>
<p>资源可能由一个或多个URL对应，而一个URL只能对应一个资源</p>
<ul>
<li>无状态</li>
</ul>
<p>服务器不会保存客户端的信息，每次客户端发送的请求会包含所有必须的状态信息，这样对于资源的操作是<strong>没有上下文的影响</strong></p>
<h2 id="REST-API设计规范"><a href="#REST-API设计规范" class="headerlink" title="REST API设计规范"></a>REST API设计规范</h2><h3 id="HTTP动作"><a href="#HTTP动作" class="headerlink" title="HTTP动作"></a>HTTP动作</h3><table>
<thead>
<tr>
<th>HTTP请求方法</th>
<th></th>
</tr>
</thead>
<tbody><tr>
<td>GET</td>
<td>查询资源</td>
</tr>
<tr>
<td>POST</td>
<td>新建资源</td>
</tr>
<tr>
<td>PUT</td>
<td>更新资源</td>
</tr>
<tr>
<td>DELETE</td>
<td>删除资源</td>
</tr>
<tr>
<td>PATCH</td>
<td>部分更新（用的很少）</td>
</tr>
</tbody></table>
<h3 id="路径"><a href="#路径" class="headerlink" title="路径"></a>路径</h3><p>通常RESTful API的path为</p>
<pre class=" language-java"><code class="language-java"><span class="token operator">/</span>version<span class="token operator">/</span>resources<span class="token operator">/</span>resource_id</code></pre>
<ul>
<li>version : API的版本号</li>
<li>resources : 资源</li>
<li>resources_id : 资源id</li>
</ul>
<p>资源也可以包含子资源</p>
<pre class=" language-java"><code class="language-java"><span class="token comment" spellcheck="true">/*某个班级下的所有老师*/</span>
<span class="token operator">/</span>classes<span class="token operator">/</span><span class="token number">1</span><span class="token operator">/</span>teachers</code></pre>
<p>当增删改查不能满足业务时，可在路径上加上action</p>
<pre class=" language-java"><code class="language-java"><span class="token operator">/</span>version<span class="token operator">/</span>resources<span class="token operator">/</span>resource_id<span class="token operator">/</span>action</code></pre>
<p><strong>接口命名规范</strong></p>
<ul>
<li>接口是表示资源，因此不使用动词，使用名词，而且用名词的复数形式，如<code>/classes</code></li>
<li>所有单词使用英语小写，不使用大写</li>
<li>连字符用中杠<code>-</code>，不使用下杠<code>_</code></li>
</ul>
<h3 id="过滤信息"><a href="#过滤信息" class="headerlink" title="过滤信息"></a>过滤信息</h3><p>当查询时需要特殊条件时，使用URL参数的方式</p>
<pre class=" language-java"><code class="language-java"><span class="token operator">/</span>classes<span class="token operator">?</span>name<span class="token operator">=</span><span class="token number">19</span>级<span class="token number">1</span>班</code></pre>
<h3 id="状态码"><a href="#状态码" class="headerlink" title="状态码"></a>状态码</h3><p><strong>状态码范围：</strong></p>
<pre class=" language-java"><code class="language-java">1xx：相关信息
2xx：操作成功
3xx：重定向
4xx：客户端错误
5xx：服务器错误</code></pre>
<table>
<thead>
<tr>
<th>2xx：成功</th>
<th>3xx：重定向</th>
<th>4xx：客户端错误</th>
<th>5xx：服务器错误</th>
</tr>
</thead>
<tbody><tr>
<td>200 查询成功</td>
<td>301 永久重定向</td>
<td>400 错误请求</td>
<td>500 服务器错误</td>
</tr>
<tr>
<td>201 创建或更新成功</td>
<td>304 资源未修改</td>
<td>401 未授权</td>
<td>502 网关错误</td>
</tr>
<tr>
<td>202 请求进入后台排队（异步）</td>
<td></td>
<td>403 禁止访问</td>
<td>504 网关超时</td>
</tr>
<tr>
<td>204 用户删除成功</td>
<td></td>
<td>404 未找到</td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td>405 请求方法不对</td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td>406 请求格式不可得</td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td>410 请求资源被永久删除</td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td>422 创建对象时发生验证错误</td>
<td></td>
</tr>
</tbody></table>
<h2 id="练习"><a href="#练习" class="headerlink" title="练习"></a>练习</h2><p>简单的练练，建立一个web项目，用的spring boot</p>
<p>结构：po，mapper，controller</p>
<pre class=" language-java"><code class="language-java"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">User</span> <span class="token punctuation">{</span>
    <span class="token keyword">private</span> Integer id<span class="token punctuation">;</span>
    <span class="token keyword">private</span> String username<span class="token punctuation">;</span>
    <span class="token keyword">private</span> String password<span class="token punctuation">;</span>

    <span class="token comment" spellcheck="true">/*省略getter and setter*/</span>
<span class="token punctuation">}</span></code></pre>
<pre class=" language-java"><code class="language-java"><span class="token annotation punctuation">@Mapper</span>
<span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">UserMapper</span> <span class="token punctuation">{</span>
    <span class="token annotation punctuation">@Select</span><span class="token punctuation">(</span><span class="token string">"select * from user"</span><span class="token punctuation">)</span>
    List<span class="token operator">&lt;</span>User<span class="token operator">></span> <span class="token function">getAllUser</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">;</span>
    <span class="token annotation punctuation">@Select</span><span class="token punctuation">(</span><span class="token string">"select * from user where id = #{id}"</span><span class="token punctuation">)</span>
    User <span class="token function">getUserById</span><span class="token punctuation">(</span><span class="token keyword">int</span> id<span class="token punctuation">)</span> <span class="token punctuation">;</span>
    <span class="token annotation punctuation">@Insert</span><span class="token punctuation">(</span><span class="token string">"insert into user(username,password) values(#{user.username},#{user.password})"</span><span class="token punctuation">)</span>
    <span class="token keyword">boolean</span> <span class="token function">addUser</span><span class="token punctuation">(</span><span class="token annotation punctuation">@Param</span><span class="token punctuation">(</span><span class="token string">"user"</span><span class="token punctuation">)</span> User user<span class="token punctuation">)</span> <span class="token punctuation">;</span>
    <span class="token annotation punctuation">@Update</span><span class="token punctuation">(</span><span class="token string">"update user set username=#{user.username},password=#{user.password} where id = #{user.id}"</span><span class="token punctuation">)</span>
    <span class="token keyword">boolean</span> <span class="token function">updateUser</span><span class="token punctuation">(</span><span class="token annotation punctuation">@Param</span><span class="token punctuation">(</span><span class="token string">"user"</span><span class="token punctuation">)</span> User user<span class="token punctuation">)</span> <span class="token punctuation">;</span>
    <span class="token annotation punctuation">@Delete</span><span class="token punctuation">(</span><span class="token string">"delete from user where id = #{id}"</span><span class="token punctuation">)</span>
    <span class="token keyword">boolean</span> <span class="token function">deleteUserById</span><span class="token punctuation">(</span><span class="token keyword">int</span> id<span class="token punctuation">)</span> <span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<pre class=" language-java"><code class="language-java"><span class="token annotation punctuation">@RequestMapping</span><span class="token punctuation">(</span><span class="token string">"users"</span><span class="token punctuation">)</span>
<span class="token annotation punctuation">@RestController</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">UserController</span> <span class="token punctuation">{</span>
    <span class="token annotation punctuation">@Autowired</span><span class="token punctuation">(</span>required <span class="token operator">=</span> <span class="token boolean">false</span><span class="token punctuation">)</span>
    <span class="token keyword">private</span> UserMapper userMapper<span class="token punctuation">;</span>
    <span class="token annotation punctuation">@GetMapping</span><span class="token punctuation">(</span><span class="token string">""</span><span class="token punctuation">)</span>
    <span class="token keyword">public</span> List<span class="token operator">&lt;</span>User<span class="token operator">></span> <span class="token function">getUsers</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> userMapper<span class="token punctuation">.</span><span class="token function">getAllUser</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token annotation punctuation">@GetMapping</span><span class="token punctuation">(</span><span class="token string">"/{id}"</span><span class="token punctuation">)</span>
    <span class="token keyword">public</span> User <span class="token function">getUser</span><span class="token punctuation">(</span><span class="token annotation punctuation">@PathVariable</span> <span class="token keyword">int</span> id<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> userMapper<span class="token punctuation">.</span><span class="token function">getUserById</span><span class="token punctuation">(</span>id<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token annotation punctuation">@PostMapping</span><span class="token punctuation">(</span><span class="token string">""</span><span class="token punctuation">)</span>
    <span class="token keyword">public</span> <span class="token keyword">boolean</span> <span class="token function">addUser</span><span class="token punctuation">(</span><span class="token annotation punctuation">@RequestBody</span> User user<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> userMapper<span class="token punctuation">.</span><span class="token function">addUser</span><span class="token punctuation">(</span>user<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token annotation punctuation">@PutMapping</span><span class="token punctuation">(</span><span class="token string">""</span><span class="token punctuation">)</span>
    <span class="token keyword">public</span> <span class="token keyword">boolean</span> <span class="token function">updateUser</span><span class="token punctuation">(</span><span class="token annotation punctuation">@RequestBody</span> User user<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> userMapper<span class="token punctuation">.</span><span class="token function">updateUser</span><span class="token punctuation">(</span>user<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token annotation punctuation">@DeleteMapping</span><span class="token punctuation">(</span><span class="token string">"/{id}"</span><span class="token punctuation">)</span>
    <span class="token keyword">public</span> <span class="token keyword">boolean</span> <span class="token function">deleteUser</span><span class="token punctuation">(</span><span class="token annotation punctuation">@PathVariable</span> <span class="token keyword">int</span> id<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> userMapper<span class="token punctuation">.</span><span class="token function">deleteUserById</span><span class="token punctuation">(</span>id<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<h2 id="测试"><a href="#测试" class="headerlink" title="测试"></a>测试</h2><p>使用<strong>MockMvc</strong>进行测试</p>
<pre class=" language-java"><code class="language-java"><span class="token annotation punctuation">@RunWith</span><span class="token punctuation">(</span>SpringRunner<span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span>
<span class="token annotation punctuation">@SpringBootTest</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">UserControllerTest</span> <span class="token punctuation">{</span>
    <span class="token keyword">private</span> MockMvc mvc<span class="token punctuation">;</span>
    <span class="token annotation punctuation">@Autowired</span>
    <span class="token keyword">private</span> WebApplicationContext webApplicationContext<span class="token punctuation">;</span>
    <span class="token keyword">private</span> RequestBuilder request<span class="token punctuation">;</span>

    <span class="token annotation punctuation">@Before</span>
    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">setup</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        mvc <span class="token operator">=</span> MockMvcBuilders<span class="token punctuation">.</span><span class="token function">webAppContextSetup</span><span class="token punctuation">(</span>webApplicationContext<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">build</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token annotation punctuation">@Test</span>
    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">testGet</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">throws</span> Exception <span class="token punctuation">{</span>
        request <span class="token operator">=</span> <span class="token function">get</span><span class="token punctuation">(</span><span class="token string">"/users"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        mvc<span class="token punctuation">.</span><span class="token function">perform</span><span class="token punctuation">(</span>request<span class="token punctuation">)</span>
                <span class="token punctuation">.</span><span class="token function">andExpect</span><span class="token punctuation">(</span><span class="token function">status</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">isOk</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

        request <span class="token operator">=</span> <span class="token function">get</span><span class="token punctuation">(</span><span class="token string">"/users/1"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        MvcResult result <span class="token operator">=</span> mvc<span class="token punctuation">.</span><span class="token function">perform</span><span class="token punctuation">(</span>request<span class="token punctuation">)</span>
                <span class="token punctuation">.</span><span class="token function">andExpect</span><span class="token punctuation">(</span><span class="token function">status</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">isOk</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
                <span class="token punctuation">.</span><span class="token function">andReturn</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

        System<span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>result<span class="token punctuation">.</span><span class="token function">getResponse</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getContentAsString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token annotation punctuation">@Test</span>
    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">testPost</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">throws</span> Exception <span class="token punctuation">{</span>
        request <span class="token operator">=</span> <span class="token function">post</span><span class="token punctuation">(</span><span class="token string">"/users"</span><span class="token punctuation">)</span>
                <span class="token punctuation">.</span><span class="token function">contentType</span><span class="token punctuation">(</span>MediaType<span class="token punctuation">.</span>APPLICATION_JSON<span class="token punctuation">)</span>
                <span class="token punctuation">.</span><span class="token function">content</span><span class="token punctuation">(</span><span class="token string">"{\"username\":\"haichao\",\"password\":\"333\"}"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        mvc<span class="token punctuation">.</span><span class="token function">perform</span><span class="token punctuation">(</span>request<span class="token punctuation">)</span>
                <span class="token punctuation">.</span><span class="token function">andExpect</span><span class="token punctuation">(</span><span class="token function">status</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">isOk</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
                <span class="token punctuation">.</span><span class="token function">andExpect</span><span class="token punctuation">(</span><span class="token function">content</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">string</span><span class="token punctuation">(</span><span class="token function">equalTo</span><span class="token punctuation">(</span><span class="token string">"true"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token annotation punctuation">@Test</span>
    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">testPut</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">throws</span> Exception <span class="token punctuation">{</span>
        request <span class="token operator">=</span> <span class="token function">put</span><span class="token punctuation">(</span><span class="token string">"/users"</span><span class="token punctuation">)</span>
                <span class="token punctuation">.</span><span class="token function">contentType</span><span class="token punctuation">(</span>MediaType<span class="token punctuation">.</span>APPLICATION_JSON<span class="token punctuation">)</span>
                <span class="token punctuation">.</span><span class="token function">content</span><span class="token punctuation">(</span><span class="token string">"{\"id\":1,\"username\":\"www\",\"password\":\"333\"}"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

        mvc<span class="token punctuation">.</span><span class="token function">perform</span><span class="token punctuation">(</span>request<span class="token punctuation">)</span>
                <span class="token punctuation">.</span><span class="token function">andExpect</span><span class="token punctuation">(</span><span class="token function">status</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">isOk</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
                <span class="token punctuation">.</span><span class="token function">andExpect</span><span class="token punctuation">(</span><span class="token function">content</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">string</span><span class="token punctuation">(</span><span class="token function">equalTo</span><span class="token punctuation">(</span><span class="token string">"true"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token annotation punctuation">@Test</span>
    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">testDelete</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">throws</span> Exception <span class="token punctuation">{</span>
        request <span class="token operator">=</span> <span class="token function">delete</span><span class="token punctuation">(</span><span class="token string">"/users/1"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

        mvc<span class="token punctuation">.</span><span class="token function">perform</span><span class="token punctuation">(</span>request<span class="token punctuation">)</span>
                <span class="token punctuation">.</span><span class="token function">andExpect</span><span class="token punctuation">(</span><span class="token function">status</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">isOk</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
                <span class="token punctuation">.</span><span class="token function">andExpect</span><span class="token punctuation">(</span><span class="token function">content</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">string</span><span class="token punctuation">(</span><span class="token function">equalTo</span><span class="token punctuation">(</span><span class="token string">"true"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>注意，有些函数报错是需要引用对应的静态函数</p>
<pre class=" language-java"><code class="language-java"><span class="token keyword">import</span> <span class="token keyword">static</span> org<span class="token punctuation">.</span>hamcrest<span class="token punctuation">.</span>Matchers<span class="token punctuation">.</span>equalTo<span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token keyword">static</span> org<span class="token punctuation">.</span>springframework<span class="token punctuation">.</span>test<span class="token punctuation">.</span>web<span class="token punctuation">.</span>servlet<span class="token punctuation">.</span>request<span class="token punctuation">.</span>MockMvcRequestBuilders<span class="token punctuation">.</span>*<span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token keyword">static</span> org<span class="token punctuation">.</span>springframework<span class="token punctuation">.</span>test<span class="token punctuation">.</span>web<span class="token punctuation">.</span>servlet<span class="token punctuation">.</span>result<span class="token punctuation">.</span>MockMvcResultMatchers<span class="token punctuation">.</span>content<span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token keyword">static</span> org<span class="token punctuation">.</span>springframework<span class="token punctuation">.</span>test<span class="token punctuation">.</span>web<span class="token punctuation">.</span>servlet<span class="token punctuation">.</span>result<span class="token punctuation">.</span>MockMvcResultMatchers<span class="token punctuation">.</span>status<span class="token punctuation">;</span></code></pre>
<h3 id="MockMvc介绍"><a href="#MockMvc介绍" class="headerlink" title="MockMvc介绍"></a>MockMvc介绍</h3><p>MockMvc可以用来模拟客户端请求，用于测试</p>
<h3 id="MockMvc使用"><a href="#MockMvc使用" class="headerlink" title="MockMvc使用"></a>MockMvc使用</h3><ul>
<li>引入依赖</li>
</ul>
<pre class=" language-java"><code class="language-java"><span class="token operator">&lt;</span>dependency<span class="token operator">></span>
    <span class="token operator">&lt;</span>groupId<span class="token operator">></span>org<span class="token punctuation">.</span>springframework<span class="token punctuation">.</span>boot<span class="token operator">&lt;</span><span class="token operator">/</span>groupId<span class="token operator">></span>
    <span class="token operator">&lt;</span>artifactId<span class="token operator">></span>spring<span class="token operator">-</span>boot<span class="token operator">-</span>starter<span class="token operator">-</span>test<span class="token operator">&lt;</span><span class="token operator">/</span>artifactId<span class="token operator">></span>
    <span class="token operator">&lt;</span>scope<span class="token operator">></span>test<span class="token operator">&lt;</span><span class="token operator">/</span>scope<span class="token operator">></span>
<span class="token operator">&lt;</span><span class="token operator">/</span>dependency<span class="token operator">></span></code></pre>
<ul>
<li>实例化MockMvc<ul>
<li>主要由两个实现：<strong>StandaloneMockMvcBuilder</strong>和<strong>DefaultMockMvcBuilder</strong></li>
<li>也可以直接使用<strong>静态工厂MockMvcBuilders创建</strong>即可，不需要直接使用上面两个实现类</li>
</ul>
</li>
</ul>
<pre class=" language-java"><code class="language-java"><span class="token annotation punctuation">@Before</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">setup</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token comment" spellcheck="true">// 实例化方式1 通过参数指定控制器，这样就不需要从上下文获取</span>
    mvc <span class="token operator">=</span> MockMvcBuilders<span class="token punctuation">.</span><span class="token function">standaloneSetup</span><span class="token punctuation">(</span>UserController<span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">build</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token comment" spellcheck="true">// 实例化方式2 指定WebApplicationContext，将会从该上下文获取相应的控制器并得到相应的MockMvc</span>
    mvc <span class="token operator">=</span> MockMvcBuilders<span class="token punctuation">.</span><span class="token function">webAppContextSetup</span><span class="token punctuation">(</span>webApplicationContext<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">build</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code></pre>
<ul>
<li>相关API<ul>
<li><code>perform()</code> 执行一个MockMvcRequestBuilders请求</li>
<li><code>andExpect()</code>添加MockMvcResultMatcher验证规则，验证控制器执行完成后结果是否正确</li>
<li><code>andDo()</code>添加 MockMvcResultHandlers结果处理器，比如调试时打印结果到控制台</li>
<li><code>andReturn()</code>返回相应的MvcResult，然后进行自定义验证/进行下一步的异步处理</li>
</ul>
</li>
<li>常用测试——&gt;网上关键词搜索</li>
</ul>
<h3 id="遇到的坑"><a href="#遇到的坑" class="headerlink" title="遇到的坑"></a>遇到的坑</h3><ul>
<li>测试类的包路径要和springboot的主启动程序类的路径相同或在下级目录中</li>
<li><code>@Test</code>注解导入包是<code>import org.junit.Test;</code>而不是<code>import org.junit.jupiter.api.Test;</code></li>
<li>使用实例化方式1<code>standaloneSetup</code>创建MockMvc会报空指针异常，该问题未解决</li>
</ul>
<h2 id="结语"><a href="#结语" class="headerlink" title="结语"></a>结语</h2><p>RESTful只是一种风格，而不是一种标准或约束，在使用中按照具体项目需求进行更改，过分追求完美的RESTful会使成本大大增加</p>

  </article>

  
      
    <div class="nexmoe-post-copyright">
        <strong>本文作者：</strong>塔纳托斯<br>
        <strong>本文链接：</strong><a href="http://hai-chao.gitee.io/blog/2022/01/29/25.shi-yong-restful-feng-ge/" title="http:&#x2F;&#x2F;hai-chao.gitee.io&#x2F;blog&#x2F;2022&#x2F;01&#x2F;29&#x2F;25.shi-yong-restful-feng-ge&#x2F;" target="_blank" rel="noopener">http:&#x2F;&#x2F;hai-chao.gitee.io&#x2F;blog&#x2F;2022&#x2F;01&#x2F;29&#x2F;25.shi-yong-restful-feng-ge&#x2F;</a><br>
        
            <strong>版权声明：</strong>本文采用 <a href="https://creativecommons.org/licenses/by-nc-sa/3.0/cn/deed.zh" target="_blank">CC BY-NC-SA 3.0 CN</a> 协议进行许可
        
    </div>


  
  
  <div class="nexmoe-post-meta nexmoe-rainbow">
    
    
        <a class="nexmoefont icon-tag-fill -none-link" href="/blog/tags/%E5%AD%A6%E4%B9%A0/" rel="tag">学习</a>
    
</div>

  
      <div class="nexmoe-post-footer">
          
      </div>
  
</div>
            <div class="nexmoe-post-right">
              <div class="nexmoe-fixed">
                  <div class="nexmoe-tool"> 
                    
                      
                        
                          
                          
                              <button class="mdui-fab catalog" style="overflow:unset;">
                                  <i class="nexmoefont icon-i-catalog"></i>
                                  <div class="nexmoe-toc">
                                      <ol class="toc"><li class="toc-item toc-level-2"><a class="toc-link" href="#REST%E4%BB%8B%E7%BB%8D"><span class="toc-number">1.</span> <span class="toc-text">REST介绍</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#REST-API%E8%AE%BE%E8%AE%A1%E8%A7%84%E8%8C%83"><span class="toc-number">2.</span> <span class="toc-text">REST API设计规范</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#HTTP%E5%8A%A8%E4%BD%9C"><span class="toc-number">2.1.</span> <span class="toc-text">HTTP动作</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E8%B7%AF%E5%BE%84"><span class="toc-number">2.2.</span> <span class="toc-text">路径</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E8%BF%87%E6%BB%A4%E4%BF%A1%E6%81%AF"><span class="toc-number">2.3.</span> <span class="toc-text">过滤信息</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E7%8A%B6%E6%80%81%E7%A0%81"><span class="toc-number">2.4.</span> <span class="toc-text">状态码</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E7%BB%83%E4%B9%A0"><span class="toc-number">3.</span> <span class="toc-text">练习</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%B5%8B%E8%AF%95"><span class="toc-number">4.</span> <span class="toc-text">测试</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#MockMvc%E4%BB%8B%E7%BB%8D"><span class="toc-number">4.1.</span> <span class="toc-text">MockMvc介绍</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#MockMvc%E4%BD%BF%E7%94%A8"><span class="toc-number">4.2.</span> <span class="toc-text">MockMvc使用</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E9%81%87%E5%88%B0%E7%9A%84%E5%9D%91"><span class="toc-number">4.3.</span> <span class="toc-text">遇到的坑</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E7%BB%93%E8%AF%AD"><span class="toc-number">5.</span> <span class="toc-text">结语</span></a></li></ol>
                                  </div>
                              </button>
                          
                          
                      
                    
                      <a href="#nexmoe-content" class="toc-link" aria-label="回到顶部" title="top"><button class="mdui-fab mdui-ripple"><i class="nexmoefont icon-caret-top"></i></button></a>
                  </div>
              </div>
            </div>
        </div>
    </div>
    
    <script src="https://cdn.jsdelivr.net/combine/npm/lazysizes@5.1.0/lazysizes.min.js,npm/mdui@0.4.3/dist/js/mdui.min.js?v=1"></script>
<script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/gh/fancyapps/fancybox@3.5.7/dist/jquery.fancybox.min.js"></script>

 

<script async src="/blog/js/app.js?v=1679297521094"></script>



<script src="https://cdn.jsdelivr.net/npm/justifiedGallery@3.8.1/dist/js/jquery.justifiedGallery.min.js"></script>
<script>
	$(".justified-gallery").justifiedGallery({
		rowHeight: 160,
		margins: 10,
	});
</script>


    





</body>

</html>
